import {ComplexPropertyValue, PromiseMabe, VJsonComponentProp} from "./types";
import {VJsonComponentBase} from "./factory";
import {applyComplexValue, applyValue, isPromise} from "./utils/helper";
import * as Extend from './extend'
import _ from 'lodash'
import {reaction, toJS} from "mobx";
import {ApiDataType, ApiMethod, ApiObject, ApiResult} from "./ajax";
import {serverInvoke} from "./service";
import {IReactionDisposer} from "mobx/lib/internal";

export interface RefreshMode {
    isExportData?: boolean,
    resetPage?: boolean,
    refreshLess?: boolean
}

export function defaultMode(param?: RefreshMode) {
    if (!param) {
        param = {
            isExportData: false,
            resetPage: true,
            refreshLess: false
        }
    }
    if (!_.has(param, 'isExportData')) {
        param.isExportData = false
    }
    if (!_.has(param, 'resetPage')) {
        param.resetPage = true
    }
    if (!_.has(param, 'refreshLess')) {
        param.refreshLess = false
    }
    return param
}

/**
 * 数据组件的公共基类
 */
export abstract class VJsonDataComponentBase<CTL, JSON extends DataComponentProp<CTL>, S extends DataComponentState> extends VJsonComponentBase<JSON, S> {
    static defaultProps = {
        loading: false,
        autoDataSource: true,
        idField: 'value',
        labelField: 'label',
        parentField: 'parent',
    }

    // @ts-ignore
    state!: S

    props!: VJsonComponentProp<JSON>

    readonly dataBind: string
    protected isOverwriteAutoRefresh = false
    private _dataSource?: DataSource3 | DataSource4 | DataSource6
    onDataSourceBefore?: (sender: CTL, api: ApiObject, param?:RefreshMode) => ComplexArrayResult<any>
    onDataSourceAfter?: (sender: CTL, dataOrgin: any[], responseRaw: any, api: ApiObject, param?:RefreshMode) => ComplexArrayResult<any>
    onDataSourceFinish?: (sender: CTL) => void
    private _dataSourceWatchChain: IReactionDisposer[] = []

    /**
     * 请求是否被阻截
     */
    private _throttle: boolean = false

    protected constructor(props: VJsonComponentProp<JSON>) {
        super(props);

        this.dataBind = props.vjson.dataBind
        this.onDataSourceBefore = props.vjson.onDataSourceBefore
        this.onDataSourceAfter = props.vjson.onDataSourceAfter
        this.onDataSourceFinish = props.vjson.onDataSourceFinish
        // 这里会安装 DataSource 观察器
        this.dataSource = props.vjson.dataSource
        // delete props.vjson.dataSource

        const scope = this.props.$context.scopeInstance

        if (this.dataBind) {
            if (props.vjson.data) {
                // 直接赋值数据, 使用后, 数据会转移至 dataBind 所在位置
                this.data = toJS(props.vjson.data)
                this.exportData = this.data
            }
        } else {
            this.state = {
                ...this.state,
                data: toJS(props.vjson.data),
                exportData: toJS(props.vjson.data),
                loading: false
            }
        }
        // delete props.vjson.data
    }

    componentDidMount() {
        super.componentDidMount();

        if (!this.isOverwriteAutoRefresh &&
            this.props.vjson.dataSource &&
            this.props.vjson.autoDataSource) {
            this.refresh();
        }
    }

    get data() {
        if (this.dataBind) {
            return _.get(this.props.$context.scopeInstance, this.dataBind + '.data')
        }
        // @ts-ignore
        return this.state.data
    }

    set data(value: any[]) {
        if (this.dataBind) {
            _.set(this.props.$context.scopeInstance, this.dataBind + '.data', value)
        } else {
            this.setState({
                // @ts-ignore
                data: value
            })
        }
    }

    set refreshLessData(value: any[]) {

    }

    get exportData() {
        // @ts-ignore
        return this.state.exportData
    }

    set exportData(value: any[]) {
        this.setState({
            // @ts-ignore
            exportData: value
        })
    }

    get loading() {
        if (this.dataBind) {
            return _.get(this.props.$context.scopeInstance, this.dataBind + '.loading')
        }
        // @ts-ignore
        return this.state.loading
    }

    set loading(value: boolean) {
        if (this.dataBind) {
            _.set(this.props.$context.scopeInstance, this.dataBind + '.loading', value)
        } else {
            this.setState({
                // @ts-ignore
                loading: value
            })
        }
    }

    get dataSource() {
        return this._dataSource
    }

    resetPage: boolean = true

    set dataSource(v: any) {
        const me = this
        const scope = this.props.$context.scopeInstance

        // 重新设置 dataSource 要释放老的 Watch
        this.disposeDataSourceWatches()

        this._dataSource = toJS(v)

        if (typeof this._dataSource === 'object' &&
            'params' in this._dataSource &&
            typeof this._dataSource.params === 'object') {

            // 扫描新的 watches
            _.forOwn(this._dataSource.params, (value, key) => {
                // @ts-ignore
                if (value && typeof value === 'object' && typeof value.$watch === 'function') {

                    if (Extend.isDebugMode()) {
                        console.log('ValueWatch ', this.toString(), '.dataSourceParamWatch', ' [', key, '=', value, ']')
                    }

                    const disposer = reaction(
                        // @ts-ignore
                        value.$watch.bind(scope),
                        (watchResult: PromiseMabe<any>) => {
                            me.refresh()
                        }
                    )

                    this._dataSourceWatchChain.push(disposer)
                }
            })
        }
    }

    /**
     * 释放所有 DataSource 观察器
     */
    private disposeDataSourceWatches() {
        _.forEach(this._dataSourceWatchChain, disposer => disposer())
        this._dataSourceWatchChain = []
    }

    componentWillUnmount() {
        super.componentWillUnmount();
        this.disposeDataSourceWatches()
    }

    /**
     * 自定义 serverJS 方法
     */
    protected serverJsParamsParser(apiObject: ApiObject, param: RefreshMode = defaultMode()): Promise<ApiObject> {
        return new Promise(resolve => {
            resolve(apiObject)
        })
    }

    refresh(param: RefreshMode = defaultMode()) {
        param = defaultMode(param)
        const me = this
        if (me.loading) {
            console.error('正在请求中, 请求被安排至下一次刷新')
            me._throttle = true
            return
        }

        const scope = this.props.$context.scopeInstance
        const dataSource = this.dataSource
        if (Extend.isDebugMode()) {
            console.info('grid ' + this + ' Refresh!')
        }

        if (typeof dataSource === 'undefined' || dataSource === null) {
            // 没有 dataSource 定义
            return;
        }

        if (typeof dataSource === 'function') {
            // 方式3: JS方法
            setLoading(me, scope)
            const dataSourceResult = dataSource.call(scope, me, param)
            applyDataResult(me, scope, dataSourceResult, param)
            return;
        }

        // 解析并获取 params 带定参(或不定参)的情况
        applyParams(me, scope, dataSource.params).then(paramData => {

            if (typeof dataSource.func === 'function') {
                // 方式4/5: JS方法
                setLoading(me, scope)
                const param1 = {
                    data: paramData,
                }
                // @ts-ignore
                applyValue(me.serverJsParamsParser.call(me, param1, param)).then(() => {
                    const dataSourceResult = dataSource.func.call(scope, param1, param)
                    applyDataResult(me, scope, dataSourceResult, param)
                    return
                })
            }

            if ('url' in dataSource || typeof dataSource.func === 'symbol') {
                // 解析 url 或 服务端方法
                applyComplexValue(scope, dataSource.url).then(url => {

                    const realApi = {
                        url,
                        method: dataSource.method || "post-json",
                        headers: dataSource.headers,
                        dataType: dataSource.dataType,
                        data: _.cloneDeep(paramData),
                    }

                    if (typeof dataSource.func === 'symbol') {
                        realApi.url = Symbol.keyFor(dataSource.func)
                        realApi.method = 'server'
                    }

                    // 需要造一个 onDataSourceBefore 空方法
                    const onDataSourceBefore = me.onDataSourceBefore || (() => undefined)

                    //进行请求前的确认
                    // @ts-ignore
                    applyValue(me.serverJsParamsParser.call(me, realApi, param)).then(() => {
                        applyValue(onDataSourceBefore.call(scope, me as any, realApi as any, param)).then(beforeResult => {

                            if (typeof beforeResult === null) {
                                // 如果返回 null 数据则清空 []
                                if (Extend.isDebugMode()) {
                                    console.log('onDataSourceBefore return null, empty data.')
                                    return
                                }
                                if (param.isExportData) {
                                    me.exportData = []
                                } else {
                                    if (param.refreshLess) {
                                        me.refreshLessData = []
                                    } else {
                                        me.data = []
                                    }
                                }

                            } else if (typeof beforeResult === 'undefined') {
                                // 如果返回 undefined , 则不拦截（继续调用）
                                if (realApi.method === 'server') {
                                    // 方式6 ServerJS 请求
                                    setLoading(me, scope)

                                    serverInvoke(realApi.url, realApi.data).then((res) => {
                                        setData(me, scope, res.data, res, realApi as any, param)

                                    }).catch((e) => {
                                        setFinish(me, scope)
                                    })
                                    return

                                } else {
                                    // 方式7/8 Ajax
                                    setLoading(me, scope)
                                    Extend.ajax.func!(realApi as any).then((res) => {
                                        setData(me, scope, res.data, res, realApi as any, param)

                                    }).catch((e) => {
                                        setFinish(me, scope)
                                    })
                                    return
                                }
                            } else {
                                // 如果返回 any[] 或 Promise<any[]> 则取消请求，以返回值为主
                                if (param.isExportData) {
                                    me.exportData = beforeResult as any[]
                                } else {
                                    if (param.refreshLess) {
                                        me.refreshLessData = beforeResult as any[]
                                    } else {
                                        me.data = beforeResult as any[]
                                    }
                                }
                            }
                        })
                    })
                })
            }
        })
    }
}

function applyParams(me: any, scope: any, params?: () => PromiseMabe<any> | { [key: string]: ComplexPropertyValue<number | string> }): Promise<any> {
    return new Promise<any>(resolve => {

        if (!params) {
            // 没有参数设置，直接返回空参数
            resolve({})
            return
        }

        if (typeof params === 'function') {
            // 动态参数
            applyValue(params.call(scope)).then(res => {
                resolve(res)
            })

        } else {
            // 静态参数
            const promiseList: Promise<any>[] = []
            const keys: string[] = []
            _.forOwn(params, (value, key) => {
                keys.push(key)
                promiseList.push(applyComplexValue(scope, value))
            })

            Promise.all(promiseList).then(resList => {
                const res: any = {}
                for (let i = 0; i < resList.length; i++) {
                    res[keys[i]] = resList[i]
                }
                resolve(res)
            })
        }
    })
}

function applyDataResult(me: any, scope: any, dataResult: ComplexArrayResult<any>, param: RefreshMode = defaultMode()) {
    param = defaultMode(param)
    if (dataResult === null) {
        setData(me, scope, [], undefined, undefined, param)

    } else if (typeof dataResult === 'undefined') {
        // 直接完成，跳过当前结果
        setFinish(me, scope)

    } else if (isPromise(dataResult)) {
        (dataResult as any).then((data: any) => {
            setData(me, scope, data, data, undefined, param)

        }).catch(() => {
            setFinish(me, scope)
        })

    } else {
        setData(me, scope, dataResult, undefined, undefined, param)
    }
}

function setData(me: any, scope: any, dataOrgin: any, responseRaw?: any, api?: ApiObject, param: RefreshMode = defaultMode()) {
    param = defaultMode(param)

    if (typeof me.onDataSourceAfter === 'function') {
        // 需要后期加工数据
        // 以 onDataSourceAfter 返回的数据为主
        applyValue(me.onDataSourceAfter.call(me, me, dataOrgin, responseRaw, api, param)).then(data => {
            if (typeof data === 'undefined') {
                // 如果函数返回 undefined 数据以 dataOrgin 为主
                if (param.isExportData === true) {
                    me.exportData = dataOrgin
                } else {
                    if (param.refreshLess) {
                        me.refreshLessData = dataOrgin
                    } else {
                        me.data = dataOrgin
                    }
                }

            } else if (data === null) {
                // 如果返回了 null , 则取消本次加载的数据（不要影响现有 data）
                if (Extend.isDebugMode()) {
                    console.log('onDataSourceAfter return null, ignore Effect.')
                }

            } else {
                // 如果返回了 any[] 或 Promise<any[]> 则以返回值为主
                if (param.isExportData === true) {
                    me.exportData = data
                } else {
                    if (param.refreshLess) {
                        me.refreshLessData = data
                    } else {
                        me.data = data
                    }
                }
            }

        }).finally(() => {
            setFinish(me, scope)
        })
        return

    } else if (typeof dataOrgin === 'undefined') {
        // 如果返回了 undefined , 则取消本次加载，不改动 data
        if (Extend.isDebugMode()) {
            console.log('setData null, ignore Effect.')
            return
        }

    } else if (dataOrgin === null) {
        // 如果函数返回 null 数据则清空
        if (param.isExportData === true) {
            me.exportData = []
        } else {
            if (param.refreshLess) {
                me.refreshLessData = []
            } else {
                me.data = []
            }
        }

    } else {
        // 如果返回了 any[] 或 Promise<any[]> 则以返回值为主
        if (param.isExportData === true) {
            me.exportData = dataOrgin
        } else {
            if (param.refreshLess) {
                me.refreshLessData = dataOrgin
            } else {
                me.data = dataOrgin
            }
        }
    }
    setFinish(me, scope)
}

function setFinish(me: any, scope: any) {
    me.loading = false
    if (me._throttle) {
        me._throttle = false
        _.defer(() => {
            me.refresh()
        })
    }
}

function setLoading(me: any, scope: any) {
    me.loading = true
}

/**
 * 数据类组件属性 Prop
 */
export interface DataComponentProp<CTL> {

    /**
     * 组件挂载时自动应用 DataSource 配置加载数据, 默认 true
     */
    autoDataSource?: boolean

    /**
     * dataSource 设置，可以是函数、定参或不定参、Ajax/Server/Post等
     */
    dataSource?: DataSource3 | DataSource4 | DataSource6

    /**
     * DataSource 请求前回调 ( 直接赋值 data 不会走这个回调)
     *   如果返回 null 数据则清空 []
     *   如果返回 undefined , 则不拦截（继续调用）
     *   如果返回 any[] 或 Promise<any[]> 则取消请求，以返回值为主
     */
    onDataSourceBefore?: (sender: CTL, api: ApiObject) => ComplexArrayResult<any>

    /**
     * DataSource 返回值后回调
     *   如果返回了 null , 则取消本次加载的数据（不要影响现有 data）
     *   如果函数返回 undefined 数据以 dataOrgin 为主
     *   如果返回了 any[] 或 Promise<any[]> 则以返回值为主
     */
    onDataSourceAfter?: (sender: CTL, dataOrgin: any[], responseRaw: any, api: ApiObject, param?:RefreshMode) => ComplexArrayResult<any>

    /**
     * 数据加载完毕后回调. 直接赋值 data 不会走这个回调.
     */
    onDataSourceFinish?: (sender: CTL) => void

    /**
     * 设置是否在读取中
     */
    loading: boolean

    /**
     * 组件数据，绑定到 scope 上的属性路径
     */
    dataBind: string

    /**
     * 方式1: 直接赋值数据, 使用后, 数据会转移至 dataBind 所在位置
     * 不会走 onDataSourceBefore / onDataSourceAfter / onDataSourceFinish 回调
     * 该方法主要是为了保留简洁的 select / radio 等组件 data 赋值能正常使用
     */
    data: any[]

    /**
     * 用来与 key->value 类型组件（select / checkboxGroup / radio / cascader）绑定时，值字段名(默认 "value" 属性, 表格默认 "id" 属性)
     */
    idField: string

    /**
     * 用来与 key->value 类型组件（select / checkboxGroup / radio / cascader）绑定时，显示字段名(默认 "label" 属性)
     */
    labelField: string

    /**
     * 用来与 key->value 类型组件（select / checkboxGroup / radio / cascader）绑定时，起禁用作用的字段名，该字段没有默认值，默认不启用 disabled
     */
    disabledField: string

    /**
     * 用来生成树形结构的组件（tree / cascader）绑定时，指定父字段名
     * 如果树形组件不设置该属性，则以层级的方式 children: [] 指定下级
     */
    parentField: string
}

/**
 * 数据类组件状态 state
 */
export interface DataComponentState {

}

export type ComplexArrayResult<T> = PromiseMabe<T[]> | null | undefined

/**
 * 方式3: JS方法
 * 如果函数返回 null 数据则清空 []
 * 如果返回了 undefined , 则取消本次加载，不改动 data 属性
 * 如果返回了 any[] 或 Promise<any[]> 则以返回值为主
 */
export type DataSource3 = () => ComplexArrayResult<any>

/**
 * 方式4/5: JS方法，带定参(或不定参)的情况
 */
export type DataSource4 = {
    func: (paramData: any) => ComplexArrayResult<any>
    params?: () => ComplexArrayResult<any> | {
        [key: string]: ComplexPropertyValue<any>
    }
}

/**
 * 方式6/7/8: Server / Ajax / upload 方法
 */
export type DataSource6 = {
    url: ComplexPropertyValue<string>

    method: ApiMethod | 'server'

    dataType?: ApiDataType

    params?: () => ComplexArrayResult<any> | {
        [key: string]: ComplexPropertyValue<number | string>
    }

    headers?: () => ComplexArrayResult<any> | {
        [key: string]: ComplexPropertyValue<number | string>
    }
}

// export interface Pagination {
//     size: number
//     current: number
//     total: number
// }
//
// /**
//  * 客户端方法参数
//  */
// export interface DataSourceParam {
//     /**
//      * 数据异步获取完成之后的回调
//      * @param data 数据
//      */
//     successCallback(data: any[], pagination?: Pagination): void
//
//     /**
//      * 数据异步获取错误后的回调
//      */
//     failCallback(): void
// }
//
// /**
//  * 客户端方法参数
//  */
// export interface ApiBeforeParam {
//     /**
//      * 是否取消调用
//      */
//     isCancel: boolean
//
//     /**
//      * 实际的请求数据
//      */
//     requestApi: DataSourceAjaxApi
//
//     /**
//      * 数据异步获取完成之后的回调
//      * @param data 数据
//      */
//     successCallback(data: any[], pagination?: Pagination): void
//
//     /**
//      * 数据异步获取错误后的回调
//      */
//     failCallback(): void
// }
//
// /**
//  * api 是客户端方法
//  */
// export type DataSourceClientFunction<T> = (sender: T, option: DataSourceParam) => void | string
//
// /**
//  * api 是一套配置
//  */
// export interface DataSourceAjaxApi {
//     /**
//      * ajax 地址或 serverJS 方法
//      * serverJS 方法格式为 "/RootService@method"
//      */
//     url: string
//
//     /**
//      * 既常规 Http 请求方式,默认为 server
//      * method 如果是 server, 走 serverJS 调用方法，既：post-json
//      */
//     method?: 'server' | 'get' | 'post' | 'put' | 'patch' | 'delete' | 'download' | 'post-json' | 'post-file'
//
//     /**
//      * url是ajax地址的情况下，设定 Http 请求头
//      */
//     headers?: PlainObject
//
//     /**
//      * url是ajax地址的情况下，设定 Http-Body 格式, 默认 json
//      */
//     dataType?: 'json' | 'form-data' | 'form'
//
//     /**
//      * 请求的数据，{ $get: '实时获取实体类的值' }, { $watch: '实时获取实体类的值，并监控值的变化，如果发生变化自动再次调用 API' }
//      */
//     data: {
//         [k: string]: { $watch: string } | { $get: string } | string
//     }
// }
//

//
// /**
//  * 数据类组件状态
//  */
// export interface DataComponentState {
//     data?: any[]
// }
//
// /**
//  * 数据组件的公共基类
//  */
// export abstract class VJsonDataComponentBase<CTL, JSON extends DataComponentProp<CTL>, S extends DataComponentState> extends VJsonComponentBase<JSON, S> {
//     static defaultProps: DataComponentProp<any> = {
//         data: [],
//         autoLoad: true,
//         idField: 'value',
//         labelField: 'label',
//         parentField: 'parent',
//     }
//
//     // @ts-ignore
//     state!: S
//
//     props!: VJsonComponentProp<JSON>
//
//     _autoLoad?: boolean
//     _api?: DataSourceClientFunction<CTL> | DataSourceAjaxApi
//     _onApiBefore?: YvanEvent<any>
//     _onApiAfter?: YvanEvent<any>
//     _onApiFinish?: YvanEvent<any>
//
//     protected constructor(props: any) {
//         super(props);
//
//         this._autoLoad = props.vjson.autoLoad
//         this._api = props.vjson.api
//         this._onApiBefore = props.vjson.onApiBefore
//         this._onApiAfter = props.vjson.onApiAfter
//         this._onApiFinish = props.vjson.onApiFinish
//     }
//
//     abstract set loading(v: undefined | boolean);
//
//     get data(): any[] {
//         return this.state.data || []
//     }
//
//     set data(v) {
//         this.setState({
//             data: v
//         })
//     }
//
//     get api(): undefined | DataSourceClientFunction<CTL> | DataSourceAjaxApi {
//         return this._api
//     }
//
//     set api(v: undefined | DataSourceClientFunction<CTL> | DataSourceAjaxApi) {
//         this._api = v
//         if (!v) {
//             this.data = []
//         } else {
//             this.refresh()
//         }
//     }
//
//     // public callBackFunction:undefined | Function = undefined
//
//     private autoRunFunction: any;
//
//     /**
//      * 处理数据源参数，解析数据源里面的@watch和@get，并且在@watch的情况下执行绑定操作
//      * @param data 数据源的参数
//      */
//     paramHandle(data: any): any {
//
//         let keys: any[] = new Array();
//         let watchEntityPaths: any[] = new Array();
//         const scope = this.props.$context.scopeInstance;
//         deepTravData(data, (parent: any, obj: any, key: string, keyPath: string) => {
//             if (_.has(obj, '@watch')) {
//                 parent[key] = _.get(scope, obj['@watch']);
//                 keys.push(keyPath);
//                 watchEntityPaths.push(obj['@watch']);
//             } else if (_.has(obj, '@get')) {
//                 parent[key] = _.get(scope, obj['@get']);
//                 // entityPaths.push(obj['@get']);
//                 // keys.push(keyPath);
//             } else {
//                 return true;
//             }
//             return false;
//         }, null, '', '');
//
//         return watchEntityPaths;
//     }
//
//     componentDidMount() {
//         super.componentDidMount();
//
//         if (this._autoLoad !== false) {
//             // 需要自动加载
//             this.refresh()
//         }
//     }
// }


// /**
//  * 发起新一轮 API 请求，最终结果会写入到 data 中
//  */
// refresh() {
//     const me = this
//     const api = this.api
//     let callBackFunction: undefined | Function = undefined
//     if (!api) {
//         // 没有 api 的定义
//         return
//     }
//     let watchEntityPaths: any[];
//
//     // ================================ 根据条件获取 callBackFunction 函数 =========================
//     let realApi: any = undefined;
//     if (typeof api === 'string') {
//         callBackFunction = this.props.$context.scopeInstance[api]
//         if (!callBackFunction) {
//             console.error('无法在Scope实例中找到方法' + api, this.props.$context.scopeInstance)
//         }
//
//     } else if (typeof api === 'function') {
//         callBackFunction = api
//
//     } else if (api.url) {
//         let param = _.cloneDeep(api.data);
//         watchEntityPaths = me.paramHandle(param);
//
//         if (api.method === 'server' || typeof api.method === 'undefined' || !api.method) {
//             // 服务端方法
//             callBackFunction = (sender: CTL, e: DataSourceParam, otherParam: any) => {
//                 _.merge(param, otherParam);
//                 serverInvoke(api.url, param).then((res) => {
//                     if (res.success) {
//                         e.successCallback(res.data, res.pagination)
//                     } else {
//                         e.failCallback()
//                     }
//
//                 }).catch((err) => {
//                     console.error(err)
//                     e.failCallback()
//
//                 })
//             }
//
//         } else {
//             // Ajax 调用
//             realApi = {
//                 url: api.url as string,
//                 method: api.method || "post-json",
//                 headers: api.headers,
//                 dataType: api.dataType,
//                 data: _.cloneDeep(api.data),
//             }
//             watchEntityPaths = me.paramHandle(realApi.data);
//             callBackFunction = (sender: CTL, e: DataSourceParam, otherParam: any) => {
//                 _.merge(realApi.data, otherParam);
//                 Extend.ajax.func!(realApi).then((res) => {
//                     if (res.success) {
//                         e.successCallback(res.data, res.pagination)
//                     } else {
//                         e.failCallback()
//                     }
//
//                 }).catch((err) => {
//                     console.error(err)
//                     e.failCallback()
//
//                 })
//             }
//         }
//
//     } else {
//         throw new TypeError("没有设定 api.url")
//     }
//
//     if (!callBackFunction) {
//         console.error('无法找到 api 回调的实现')
//         return
//     }
//
//     // ================================ before / after =========================
//     this.loading = true
//     const successCallback = (data: any[]) => {
//         const dataNew = YvanEventDispatch(me._onApiAfter as any, this, data)
//         if (_.isArray(dataNew)) {
//             // onApiAfter 有返回新的数组, 以新的数组为准
//             data = dataNew
//         }
//         me.data = data
//         this.loading = false
//         YvanEventDispatch(this._onApiFinish as any, this, beforeParam)
//     }
//     const failCallback = () => {
//         // 失败，直接赋空值
//         me.data = []
//         this.loading = false
//         YvanEventDispatch(this._onApiFinish as any, this, beforeParam)
//     }
//
//     const beforeParam: ApiBeforeParam = {
//         isCancel: false,
//         requestApi: realApi,
//         successCallback,
//         failCallback
//     }
//     YvanEventDispatch(this._onApiBefore as any, this, beforeParam)
//     if (beforeParam.isCancel) {
//         // 被取消了
//         this.loading = false
//         YvanEventDispatch(this._onApiFinish as any, this, beforeParam)
//         return
//     }
//
//     const e: DataSourceParam = {
//         successCallback,
//         failCallback
//     }
//
//     // 表格存在分页的情况
//     // @ts-ignore
//     if ("Grid" === this.constructor.name) {
//         // @ts-ignore
//         const gridPage: GridPage = this.gridPage;
//
//         // 表格加载出来才会有gridPage 对象
//         if (gridPage) {
//             // @ts-ignore
//             if (this.state.pagination) {
//                 // 客户端的方法
//                 if (typeof api === 'string' || typeof api === 'function') {
//                     const tempFunc = e.successCallback;
//                     e.successCallback = (data: any[]) => {
//                         const rowCount = data.length;
//                         let d: any[] = []
//                         const startRow = (gridPage.actionPage - 1) * gridPage.actionSize
//                         let endRow = gridPage.actionPage * gridPage.actionSize
//                         endRow = endRow > rowCount ? rowCount : endRow
//
//                         for (let i = startRow; i < endRow; i++) {
//                             d.push(data[i])
//                         }
//                         tempFunc(d);
//                         gridPage.itemCount = rowCount
//                         gridPage.currentPage = gridPage.actionPage
//                     }
//                 } else {
//                     const tempFunc = e.successCallback;
//                     e.successCallback = (data: any[], pagination: Pagination) => {
//                         tempFunc(data, pagination);
//                         gridPage.itemCount = (pagination && pagination.total > 0) ? pagination.total : gridPage.itemCount;
//                         gridPage.currentPage = gridPage.actionPage
//                     }
//                 }
//                 // 表格分页操作回调事件
//                 gridPage.getPageData = (currentPage: number, pageSize: number) => {
//                     callBackFunction!.call(me.props.$context.scopeInstance, me, e, {
//                         limitOffset: (currentPage - 1) * pageSize,
//                         limit: pageSize
//                     })
//                 }
//                 // 首先执行一次
//                 callBackFunction.call(this.props.$context.scopeInstance, this, e, {
//                     limitOffset: 0,
//                     limit: gridPage.actionSize,
//                     needCount: true
//                 })
//             } else {
//                 callBackFunction.call(this.props.$context.scopeInstance, this, e, {needCount: true})
//             }
//         }
//     } else {
//         callBackFunction.call(this.props.$context.scopeInstance, this, e)
//     }
//
//     // 取消掉上次的autoRun
//     if (this.autoRunFunction && typeof this.autoRunFunction === "function") {
//         this.autoRunFunction();
//     }
//
//     const scope = this.props.$context.scopeInstance;
//     let runFlag = false;
//     this.autoRunFunction = autorun(() => {
//         // let needRefresh = false;
//         if (watchEntityPaths && watchEntityPaths.length > 0) {
//
//             for (let i = 0; i < watchEntityPaths.length; i++) {
//                 const el = watchEntityPaths[i];
//                 _.get(scope, el);
//             }
//
//             if (runFlag) {
//                 runFlag = false;
//                 // debugger
//                 me.refresh()
//             } else {
//                 runFlag = true;
//             }
//         }
//         // 延时1ms去除抖动， 也避免同时改变多个属性时候多次触发autoRun
//     }, {delay: 1})
// }
// function deepTravData(obj: any, resolver: (parent: any, obj: any, key: string, keyPath: string) => boolean, parent: any, key: string, keyPath: string) {
//     if (!resolver(parent, obj, key, keyPath)) {
//         return;
//     }
//     keyPath = keyPath.length > 0 ? keyPath + "." : ""
//     _.forOwn(obj, (value, key) => {
//         if (_.isObject(value)) {
//             deepTravData(value, resolver, obj, key, keyPath + key);
//         }
//     });
// }